package main

import (
	"encoding/json"
	"fmt"
	"github.com/robfig/cron"
	"github.com/streadway/amqp"
	"log"
	"shop/common/config"
	"shop/common/global"
	"shop/common/inits"
	"shop/common/model"
	"shop/common/untils"
	"strings"
	"sync"
	"time"
)

// 添加到main函数中，在初始化之后启动活动结束检查的定时任务
func main() {
	config.Init()
	inits.InitMysql()
	inits.InitRedis()

	// 启动活动结束检查的定时任务
	go startSeckillActivityCheck()

	rabbitmq := inits.NewRabbitMQSimple("yzy")
	simple, _ := rabbitmq.ConsumeSimple()
	forever := make(chan bool)
	var wg sync.WaitGroup
	wg.Add(1)
	go func() {
		for {
			for d := range simple {
				handleSingleMessage(d)
			}
		}
	}()
	log.Println("支付消息等待中")
	<-forever
}

// startSeckillActivityCheck 启动秒杀活动结束检查的定时任务
func startSeckillActivityCheck() {
	c := cron.New()
	// 每分钟执行一次检查
	spec := "0 */1 * * * *"
	_ = c.AddFunc(spec, func() {
		checkAndProcessEndedActivities()
	})
	c.Start()
	log.Println("秒杀活动结束检查任务已启动")

	// 防止goroutine退出
	select {}
}

// checkAndProcessEndedActivities 检查并处理已结束的秒杀活动
func checkAndProcessEndedActivities() {
	now := time.Now()
	var seckillGoodsList []model.SeckillGoods

	// 查询所有已结束但状态仍为开始的秒杀活动
	err := global.DB.Where("end_time < ? AND seckill_status = ?", now, 1).Find(&seckillGoodsList).Error
	if err != nil {
		log.Printf("查询已结束的秒杀活动失败: %v", err)
		return
	}

	for _, sg := range seckillGoodsList {
		// 执行库存返还操作
		success, err := untils.ReturnAllSeckillGoodsStock(int(sg.Id))
		if success {
			// 更新秒杀商品状态为关闭
			tx := global.DB.Begin()
			defer func() {
				if r := recover(); r != nil {
					tx.Rollback()
				}
			}()

			if err := tx.Model(&model.SeckillGoods{}).
				Where("id = ?", sg.Id).
				Update("seckill_status", 2).Error; err != nil {
				tx.Rollback()
				log.Printf("更新秒杀商品状态失败: %v", err)
				continue
			}

			if err := tx.Commit().Error; err != nil {
				tx.Rollback()
				log.Printf("事务提交失败: %v", err)
				continue
			}

			log.Printf("秒杀活动ID:%d 库存返还成功，已返还库存数量: %d 到商品ID:%d", sg.Id, sg.SeckillStock, sg.GoodId)
		} else {
			log.Printf("秒杀活动ID:%d 库存返还失败: %v", sg.Id, err)
		}
	}
}

func handleSingleMessage(d amqp.Delivery) {
	var o model.Order
	err := json.Unmarshal(d.Body, &o)
	if err != nil {
		log.Printf("消息解析失败: %v", err)
		d.Ack(false)
		return
	}
	// 重置ID字段为0，让数据库自动生成主键
	o.Id = 0

	// 异步创建订单
	err = global.DB.Create(&o).Error
	if err != nil {
		// 订单创建失败，回滚Redis虚拟库存
		if untils.ReturnSeckillGoodsStock(int(o.SeckillGoodsId), int(o.Num)) {
			log.Printf("订单创建失败，回滚库存成功 goodsId:%d", o.SeckillGoodsId)
		} else {
			log.Printf("订单创建失败，回滚库存失败 goodsId:%d", o.SeckillGoodsId)
		}

		if strings.Contains(err.Error(), "Duplicate entry") {
			log.Printf("订单已存在 goods:%d user:%d", o.SeckillGoodsId, o.UserId)
		} else {
			log.Printf("创建订单失败：%v", err)
		}
		d.Ack(false)
		return
	}

	log.Printf("订单创建成功 %s", o.OrderNo)
	d.Ack(false)

	c := Cron(o.OrderNo)

	// 安全机制：24小时后强制停止定时任务（防止漏停）
	time.AfterFunc(24*time.Hour, func() {
		c.Stop()
		log.Printf("订单 %s 的支付检查任务已强制停止", o.OrderNo)
	})
}

func Cron(order string) *cron.Cron {
	c := cron.New()
	spec := "0 */15 * * * *"
	_ = c.AddFunc(spec, func() {
		var o model.Order
		err := global.DB.Where("orderNo = ?", order).First(&o).Error
		if err != nil {
			log.Printf("查询订单失败: %v", err)
			return
		}
		if o.Status == 2 {
			err = global.DB.Where("orderNo = ?", order).Delete(&model.Order{}).Error
			if err == nil {
				if untils.ReturnSeckillGoodsStock(int(o.SeckillGoodsId), int(o.Num)) == false {
					log.Printf("订单超时未支付，回滚库存失败 key=%s", fmt.Sprintf("seckill:stock:%d", o.SeckillGoodsId))
				} else {
					log.Printf("订单超时未支付，回滚库存成功 key=%s", fmt.Sprintf("seckill:stock:%d", o.SeckillGoodsId))
				}
			} else {
				log.Printf("删除超时订单失败: %v", err)
			}
		}
	})
	c.Start()
	log.Printf("订单 %s 的支付检查任务已启动", order)
	return c
}
